package org.game.module.storebo;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.bean.StoreInfo.ServerLimit;
import org.cfg.CommodityCfg;
import org.cfg.StoreCfg;
import org.cfg.cache.CommodityCfgCache;
import org.cfg.cache.StoreCfgCache;
import org.constant.ItemType;
import org.error.GameErrorCode;
import org.game.cache.ServerLimitCommodityBuyRecordCache;
import org.game.constant.SessionConstent;
import org.game.db.bean.CommodityBuyRecord;
import org.game.db.bean.Item;
import org.game.db.bean.Player;
import org.game.db.bean.PlayerStore;
import org.game.db.cache.ItemCache;
import org.game.db.cache.PlayerStoreCache;
import org.game.db.vo.EquipmentVO;
import org.game.log.builder.LogDsp;
import org.game.log.dsp.GoodsDsp;
import org.game.manager.ItemManager;
import org.game.manager.StoreManager;
import org.game.module.storebo.handler.BagHandler;
import org.game.msgBuilder.StoreMsgBuilder;
import org.game.protobuf.c2s.C2SStoreMsg;
import org.game.protobuf.c2s.C2SStoreMsg.BuyGoods;
import org.game.protobuf.c2s.C2SStoreMsg.GetStoreInfo;
import org.game.protobuf.c2s.C2SStoreMsg.RefreshStore;
import org.game.protobuf.s2c.S2CItemMsg;
import org.game.protobuf.s2c.S2CShareMsg.ChangeType;
import org.game.protobuf.s2c.S2CShareMsg.RewardsMsg;
import org.game.protobuf.s2c.S2CStoreMsg;
import org.game.protobuf.s2c.S2CStoreMsg.CommodityBuyLogs;
import org.game.protobuf.s2c.S2CStoreMsg.DynamicCommodity;
import org.game.protobuf.s2c.S2CStoreMsg.RespDynamicCommodity;
import org.game.protobuf.s2c.S2CStoreMsg.SellInfo;
import org.game.protobuf.s2c.S2CStoreMsg.StoreDataInfo;
import org.game.util.ProtoUnit;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sojoys.artifact.constant.ArtifactErrorCode;
import com.sojoys.artifact.constant.DataModelKeyEnum;
import com.sojoys.artifact.exception.AbstractLogicModelException;
import com.sojoys.artifact.factory.session.ISession;
import com.sojoys.artifact.manager.JsonManager;
import com.sojoys.artifact.manager.MessageManager;
import com.sojoys.artifact.tools.ToolError;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.MapUtil;

/**
 * @author : DengYing
 * @CreateDate : 2017年9月11日 上午11:18:42
 * @Description ：Please describe this document
 */
public class StoreBOImpl implements StoreBO {
	@Override
	public byte[] getStoreInfo(ISession session, GetStoreInfo storeInfo) throws AbstractLogicModelException {
		Player player = session.getAttr(SessionConstent.PLAYER);

		List<Integer> cids = storeInfo.getCidList();
		StoreDataInfo.Builder storeDataInfo = StoreDataInfo.newBuilder();
		for (Integer cid : cids) {
			StoreCfg store = StoreCfgCache.me().getById(cid);
			if (store == null)
				continue;
			storeDataInfo.addStores(StoreMsgBuilder.createStoreInfoMsg(player, store));
		}
		
		return ProtoUnit.toByte(storeDataInfo.build());
	}
	
	
	@Override
	public byte[] getCommodityBuyLog(ISession session) throws AbstractLogicModelException {
		Player player = session.getAttr(SessionConstent.PLAYER);
		Set<CommodityCfg> set = new HashSet<>();
		
		// 个人限购
		List<CommodityBuyRecord> records = player.getCommodityBuyRecordsFkPlayerId();
		for (CommodityBuyRecord commodityBuyRecord : records) {
			CommodityCfg cfg = commodityBuyRecord.getCommodityBuyRecordProxy().getCfg();
			// 商品被删除
			if (cfg==null) {
				continue;
			}
			set.add(cfg);
		}
		// 全服限购
		Collection<ServerLimit> serverRecords = ServerLimitCommodityBuyRecordCache.me().getAll();
		for (ServerLimit serverLimit : serverRecords) {
			CommodityCfg cfg = CommodityCfgCache.me().getById(serverLimit.getCommodityId());
			// 商品被删除
			if (cfg==null) {
				continue;
			}
			set.add(cfg);
		}
		return ProtoUnit.toByte(StoreMsgBuilder.createBuyRecordInfo(player, set));
	}

	public static void main(String[] args) {
		Date nowDate = new Date();
		System.out.println(DateUtil.beginOfWeek(nowDate));
	}
	
	@Override
	public byte[] buy(ISession session, BuyGoods buyGoods) throws AbstractLogicModelException {
		Player player = session.getAttr(SessionConstent.PLAYER);
		int cid = buyGoods.getCid();
		int num = buyGoods.getNum();
		
		StoreManager.me().buy(player, cid, num , BagHandler.me());

		S2CStoreMsg.BuyGoods.Builder builder = S2CStoreMsg.BuyGoods.newBuilder();
        builder.setCid(cid);
        builder.setNum(num);
        return ProtoUnit.toByte(builder.build());
	}


	@Override
	public byte[] refreshStore(ISession session, RefreshStore refreshStore) throws AbstractLogicModelException {
		Player player = session.getAttr(SessionConstent.PLAYER);
		StoreCfg storeCfg = StoreCfgCache.me().getById(refreshStore.getCid());

		PlayerStore store = PlayerStoreCache.me().getPlayerStoreCacheProxy().getStoreByCid(player.getId(),storeCfg.getId());

		int[] refreshCostId = storeCfg.getRefreshCostId();
		int[] refreshCostNum = storeCfg.getRefreshCostNum();


		int todayRefreshCount = store.getTodayRefreshCount();
		int totalRefreshCount = store.getTotalRefreshCount();
		
		int index = Math.min(refreshCostId.length - 1, todayRefreshCount);
		// 道具检查
		ItemManager.checkGoodsByCid(player, MapUtil.of(refreshCostId[index], refreshCostNum[index]));
		
		LogDsp log = LogDsp.newBuilder(GoodsDsp.REFRESH_SHOP).targetTag(storeCfg.getId());
		
		ItemManager.costGoodsByCid(player,new int[]{refreshCostId[index]},new int[]{refreshCostNum[index]}, log, S2CItemMsg.ItemList.newBuilder());

		store.setTodayRefreshCount(todayRefreshCount + 1);
		store.setTotalRefreshCount(totalRefreshCount + 1);
		store.update();

		// 重置商店
		Set<CommodityCfg> affect = StoreManager.me().resetStore(player, storeCfg, false, false);
		// 推送更新
		CommodityBuyLogs commodityBuyLogs = StoreMsgBuilder.createBuyRecordInfo(player, affect);
		player.getPlayerProxy().sendMsg(MessageManager.me().create(StoreBO.getCommodityBuyLog, commodityBuyLogs.toByteArray()));
		
		
		List<StoreCfg> storeCfgs = Lists.newArrayList();
		storeCfgs.add(storeCfg);
		return ProtoUnit.toByte(StoreMsgBuilder.createRefreshStoreMsg(player, storeCfgs));
	}

	
	@Override
	public byte[] sell(ISession session, C2SStoreMsg.SellInfo sellInfo) throws AbstractLogicModelException {
		List<C2SStoreMsg.SellGoods> sellGoodsList = sellInfo.getGoodsList();
		//出售物品集合
		Map<Long,Integer> sellGoodsMap = Maps.newHashMap();
		//获得物品集合
		Map<Integer,Integer> gainGoodsMap = Maps.newHashMap();
		
		sellGoodsList.forEach(goods->{
			long id = Long.parseLong(goods.getId());
			int num = goods.getNum();
			Item item = ItemCache.me().getById(id);
			ToolError.isAndTrue(ArtifactErrorCode.PARAM_ERROR,"出售：id错误",item == null);
			ToolError.isAndTrue(ArtifactErrorCode.PARAM_ERROR,"出售：数量不足",item.getNum()<num);
			checkEquipmentForSell(item);
			sellGoodsMap.put(id,num);
			Map<Integer,Integer> priceMap  = item.getItemProxy().getCfg().getSellProfit();
			ToolError.isAndTrue(GameErrorCode.CAN_NOT_SELL,"出售：id错误",priceMap == null || priceMap.size() == 0);
			priceMap.forEach((gainId,gainNum)->{
				int n = gainGoodsMap.computeIfAbsent(gainId,number->0);
				gainGoodsMap.put(gainId,n+(gainNum * num));
			});
		});

		Player player = session.getAttr(SessionConstent.PLAYER);
		
		LogDsp log = LogDsp.newBuilder(GoodsDsp.STORE_SELL);
		LogDsp cloneLog = log.clone();
		//扣除
		ItemManager.costGoodsByDBId(player,sellGoodsMap,log, S2CItemMsg.ItemList.newBuilder());
		//获得
		ItemManager.addGoodsAndPush(player, null, null,gainGoodsMap, cloneLog);
		
		S2CStoreMsg.SellInfo.Builder builder = SellInfo.newBuilder();
		builder.setSuccess(true);
		gainGoodsMap.forEach((k,v)->{
			builder.addRewards(RewardsMsg.newBuilder().setId(k).setNum(v));			
		});
		
		return ProtoUnit.toByte(builder.build());
	}


	@Override
	public byte[] reqDynamicCommodity(ISession session) throws AbstractLogicModelException {
		Map<Integer, CommodityCfg> dynamicCommoditys = CommodityCfgCache.me().getDynamicCommoditys();
		RespDynamicCommodity.Builder builder = RespDynamicCommodity.newBuilder();
		
		DynamicCommodity.Builder b = null;
		for (Entry<Integer, CommodityCfg> e : dynamicCommoditys.entrySet()) {
			b = DynamicCommodity.newBuilder();
			b.setCt(ChangeType.DEFAULT);
			b.setData(JsonManager.me().getJson().toJson(e.getValue().toMap(DataModelKeyEnum.SOURCE)));
			builder.addDatas(b);
		}
		
		return ProtoUnit.toByte(builder.build());
	}

	private void checkEquipmentForSell(Item item){
		if (item.getItemProxy().getCfg().getSuperType() == ItemType.EQUIP){
			EquipmentVO equipmentVO = (EquipmentVO) item;
			ToolError.isAndTrue(GameErrorCode.EQUIP_IN_USE_CAN_NOT_SELL,"已装备，不能出售",equipmentVO.getHeroId() != 0);
		}
	}
}
